import { nextTick } from 'vue';

export type RectResultType<T extends boolean> = T extends true ? UniApp.NodeInfo[] : UniApp.NodeInfo;

/**
 * 获取节点信息
 * @param selector 节点选择器 #id,.class
 * @param all 是否返回所有 selector 对应的节点
 * @param scope 作用域（支付宝小程序无效）
 * @param useFields 是否使用 fields 方法获取节点信息
 * @returns 节点信息或节点信息数组
 */
export function getRect<T extends boolean>(selector: string, all: T, scope?: any, useFields?: boolean): Promise<RectResultType<T>> {
  return new Promise<RectResultType<T>>((resolve, reject) => {
    let query: UniNamespace.SelectorQuery | null = null;
    if (scope) {
      query = uni.createSelectorQuery().in(scope);
    }
    else {
      query = uni.createSelectorQuery();
    }

    const method = all ? 'selectAll' : 'select';

    const callback = (rect: UniApp.NodeInfo | UniApp.NodeInfo[]) => {
      if (all && Array.isArray(rect) && rect.length > 0) {
        resolve(rect as RectResultType<T>);
      }
      else if (!all && rect) {
        resolve(rect as RectResultType<T>);
      }
      else {
        reject(new Error('No nodes found'));
      }
    };

    if (useFields) {
      query[method](selector).fields({ size: true, node: true }, callback).exec();
    }
    else {
      query[method](selector).boundingClientRect(callback).exec();
    }
  });
}

export interface AdjustFontSizeOptions {
  maxSize: number
  minSize?: number
  scale?: number
  fontSizeRef: { value: number } // 传入 ref<number>
  queryRect: () => Promise<{ width?: number }[]> // 第一个是容器，第二个是文本元素
}

/**
 * 自动调整字体大小以适应容器宽度
 */
export async function adjustFontSizeToFit({
  maxSize,
  minSize = 8,
  fontSizeRef,
  scale = 1,
  queryRect
}: AdjustFontSizeOptions) {
  let currentSize = fontSizeRef.value || 16;
  fontSizeRef.value = currentSize;

  // 获取容器宽度
  const [wrapRect] = await queryRect();
  const boxWidth = (wrapRect?.width || 0) / scale;
  if (!boxWidth)
    return;

  let textWidth = 0;

  // 缩小字体直到合适
  while (currentSize > minSize) {
    fontSizeRef.value = currentSize;
    await nextTick();

    const [, textRect] = await queryRect();
    textWidth = (textRect?.width || 0) / scale;
    if (textWidth <= boxWidth)
      break;

    currentSize -= 1;
  }

  // 尝试增大字体直到刚好贴边
  while (currentSize < maxSize) {
    fontSizeRef.value = currentSize + 1;
    await nextTick();

    const [, textRect] = await queryRect();
    textWidth = (textRect?.width || 0) / scale;
    if (textWidth > boxWidth)
      break;

    currentSize += 1;
  }

  fontSizeRef.value = currentSize;
}
